
#define  UNICODE 1
#define  BYTE_PER_SECTOR		 512	// Size of one sector in byte - almost a standard
#define  BYTE_PER_SECTOR_WIDTH	 9		// = number of 0's in BYTE_PER_SECTOR
#include <windows.h>
#include <winioctl.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include "global.h"

// Global variables for disk and file name.
extern char           driveLetter;
extern unsigned char  fileName[];

//===============================================================================
// Static variables for card access.
static HANDLE         hDevice;

//===============================================================================
// Function: opens and initializes the card for reading and writing.
// Inputs: driveletter (global variable) - a letter to indicate the SD card drive to be accessed.
// Outputs: hDevice (global variable) - handle to the card for read and write access.
// Return: true if success, false if falied.
//===============================================================================
bool CardOpen ()
{
	unsigned int drivenumber;
	VOLUME_DISK_EXTENTS volumeDiskExtents;
	BOOL bResult;
	DWORD junk;
	TCHAR path[MAX_PATH] = {0};
	TCHAR phydisk[MAX_PATH] = {0};

	wsprintf (path, TEXT("\\\\.\\%c:"), driveLetter);				// setup the disk volume name
	hDevice = CreateFile (path,										// open disk volume to get handle
                    0,												// query only
                    FILE_SHARE_READ | FILE_SHARE_WRITE,				// sharing mode
                    NULL,											// default security attributes
                    OPEN_EXISTING,									// disposition
                    FILE_ATTRIBUTE_NORMAL,							// file attributes
                    NULL);											// do not copy file attributes
	if (hDevice == INVALID_HANDLE_VALUE)	
		return (false);												// cannot open the drive

	bResult = DeviceIoControl (hDevice,								// device to be queried
					IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,			// get physical disk location
					NULL, 0,										// no input buffer
					&volumeDiskExtents, sizeof(volumeDiskExtents),	// output buffer
					&junk,											// # bytes returned
					NULL); 

	CloseHandle (hDevice);

	if (bResult)
		drivenumber = volumeDiskExtents.Extents[0].DiskNumber;		// Get the physical disk number
	else
		return (false);												// DeviceControl error

	wsprintf (phydisk, TEXT("\\\\.\\PhysicalDrive%d"), drivenumber);	// setup physical disk name

	hDevice = CreateFile (phydisk,									// open disk volume to get handle
                    GENERIC_READ|GENERIC_WRITE,						// access mode
                    FILE_SHARE_READ|FILE_SHARE_WRITE,				// sharing mode
                    NULL,											// default security attributes
                    OPEN_EXISTING,									// disposition
                    FILE_ATTRIBUTE_NORMAL,							// file attributes
                    NULL);											// do not copy file attributes
	if (hDevice == INVALID_HANDLE_VALUE)	
		return (false);												// cannot open the drive

	return (true);
}

//===============================================================================
// Function: read the card raw data.
// Inputs: startSector - the disk sector to start reading.
//         numSector - the number of sector to read.
//         dataBuffer - pointer to the buffer to store the read data.
// Outputs: *dataBuffer - the read data.
// Return: true if success, false if falied.
//===============================================================================
bool CardRead (unsigned long startSector, unsigned long numSector, unsigned char *dataBuffer)
{
	OVERLAPPED overlapped = {0};

	overlapped.Offset = startSector * BYTE_PER_SECTOR;			// Calculate offset in bytes
	overlapped.OffsetHigh = startSector >> (32 - BYTE_PER_SECTOR_WIDTH);
	ReadFile (hDevice, dataBuffer, BYTE_PER_SECTOR * numSector, NULL, &overlapped);
	if (overlapped.InternalHigh != BYTE_PER_SECTOR)			
		return (false);											// read error

	return (true);
}

//===============================================================================
// Function: write the card raw data.
// Inputs: startSector - the disk sector to start writing.
//         numSector - the number of sector to write.
//         dataBuffer - pointer to the buffer for the write data.
// Outputs: none.
// Return: true if success, false if falied.
//===============================================================================
bool CardWrite (unsigned long startSector, unsigned long numSector, unsigned char *dataBuffer)
{
	OVERLAPPED overlapped = {0};

	overlapped.Offset = startSector * BYTE_PER_SECTOR;			// Calculate offset in bytes
	overlapped.OffsetHigh = startSector >> (32 - BYTE_PER_SECTOR_WIDTH);
	WriteFile (hDevice, dataBuffer, BYTE_PER_SECTOR * numSector, NULL, &overlapped);
	if (overlapped.InternalHigh != BYTE_PER_SECTOR)			
		return (false);											// write error

	return (true);
}

//===============================================================================
// Function: close the card.
// Inputs: none.
// Outputs: none.
// Return: true if success, false if falied.
//===============================================================================
bool CardClose ()
{
	CloseHandle (hDevice);
	return (true);
}



